package com.aspirecn.core.datacache;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;

import com.aspirecn.core.commons.Configuration;
import com.aspirecn.core.commons.FileUtils;
import com.aspirecn.core.object.City;
import com.aspirecn.core.object.Province;
import com.csvreader.CsvReader;

/**
 * 地理信息缓存
 * 包括省份、城市以及它们之间的关系信息
 * @author wangxinning
 *
 */
public class GEOCache extends BaseLocalCache {

	public final static Logger logger = Logger.getLogger(GEOCache.class);

	private List<Province> provinceList = new ArrayList<Province>();
	private List<City> cityList = new ArrayList<City>();

	private static GEOCache instance = new GEOCache();

	private Map<String, Object> map = new HashMap<String, Object>();
	private File cityFile = new File(Configuration.getInstance()
			.getDownloadFilePath() + File.separator + "city.csv");
	private File provinceFile = new File(Configuration.getInstance()
			.getDownloadFilePath() + File.separator + "province.csv");

	public List<Province> getProvinceList() {
		
		if( this.isLoading() )
		{
			return null;
		}
		
		return this.provinceList;
	}

	public List<City> getCityList() {
		
		if( this.isLoading() )
		{
			return null;
		}
		
		return this.cityList;
	}

	public Province getProvince(int nid) {
		
		String key = "p" + nid;
		return (Province) map.get(key);
	}

	/**
	 * 根据天气中定义的id查找省份信息
	 * @param nid
	 * @return
	 */
	public Province getProvinceByTianqiID(int nid) {

		if( this.isLoading() )
		{
			return null;
		}
		
		if (nid <= 0) {
			return null;
		}

		for (Province province : provinceList) {
			if (nid == province.getTianqinid()) {
				return province;
			}
		}

		return null;
	}

	/**
	 * 根据天气中定义的id查找城市信息
	 * @param nid
	 * @return
	 */
	public City getCityByTianqiID(int nid) {

		if( this.isLoading() )
		{
			return null;
		}
		
		if (nid <= 0) {
			return null;
		}

		for (City city : cityList) {
			if (nid == city.getTianqinid()) {
				return city;
			}
		}

		return null;
	}

	public City getCity(int nid) {
		
		String key = "c" + nid;
		return (City) map.get(key);
	}

	private GEOCache() {
		load();
	}

	public static GEOCache getInstance() {
		return instance;
	}

	public void load() {

		if( !loading.getAndSet(true) && Configuration.getInstance().switchGEOCache() )
		{
		
		long start = System.currentTimeMillis();
		long startMem = Runtime.getRuntime().freeMemory();
		
		try {
			if (provinceFile.exists()) {
				CsvReader reader = new CsvReader(provinceFile.toString(), ',',
						Charset.forName("gbk"));

				provinceList.clear();
				while (reader.readRecord()) {

					Province province = new Province();
					province.setNid(NumberUtils.toInt(reader.get(0)));
					province.setTianqinid(NumberUtils.toInt(reader.get(1)));
					province.setName(reader.get(2));

					provinceList.add(province);
					map.put("p" + province.getNid(), province);
				}
				
				reader.close();
			}

			if (cityFile.exists()) {

				CsvReader reader = new CsvReader(cityFile.toString(), ',',
						Charset.forName("gbk"));

				cityList.clear();
				while (reader.readRecord()) {

					City city = new City();
					city.setNid(NumberUtils.toInt(reader.get(0)));
					city.setTianqinid(NumberUtils.toInt(reader.get(1)));
					city.setName(reader.get(2));
					
					Province province = this.getProvince(NumberUtils
							.toInt(reader.get(3)));
					if (province != null) {
						province.addCity(city);
						city.setProvince(province);
					}

					map.put("c" + city.getNid(), city);
					cityList.add(city);
				}
				
				reader.close();
			}

		} catch (Exception e) {

			loading.set(false);
			logger.error("load 失败", e);
			return;
		}

		loading.set(false);
		long end = System.currentTimeMillis();
		long endMem = Runtime.getRuntime().freeMemory();
		updateFileDownloadTime();
		logger.info("省份和城市信息加载完成，time=" + (end - start) + "ms,占用内存=" + (endMem-startMem)/FileUtils.ONE_KB + "kb");
		
		}
		else
		{
			logger.info( "配置关闭，省份和城市信息未加载" );
		}
		
		loading.set(false);
	}

	@Override
	public void clear() {

		cityList.clear();
		provinceList.clear();
		map.clear();
	}

	@Override
	public void reload() {

		if( this.fileIsChange() )
		{
			this.load();
		}
		else
		{
			logger.info( "没变化，省份和城市信息未加载" );
		}
	}

	public static void main(String[] args) {
		GEOCache geoCache = GEOCache.getInstance();
		System.out.println(geoCache.getProvince(320000));
	}
	
	
	public void updateFileDownloadTime()
	{
		long fileDownloadTime1 = this.cityFile.lastModified();
		long fileDownloadTime2 = this.provinceFile.lastModified();
		
		this.fileDownloadTime = fileDownloadTime1+fileDownloadTime2;
	}
	
	
	//跟上次加载时间是否变化
	protected boolean fileIsChange()
	{
		long fileDownloadTime1 = this.cityFile.lastModified();
		long fileDownloadTime2 = this.provinceFile.lastModified();
		if( this.fileDownloadTime != fileDownloadTime1+fileDownloadTime2 )
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}